import importlib
import json
import pkgutil
import re
from string import Template


# 其他通用方法
class Common:
    # 返回该包下所有模块名称，非递归查找（只包含模块名）
    # andPackage 保留模块包名 默认 False
    @staticmethod
    def getModulesName(path, prefix, onerror=None, andPackage=False):
        names = []
        packages = pkgutil.walk_packages(path, prefix, onerror)
        for loader, name, ispkg in packages:
            if ispkg == False:
                names.append(name)
        if andPackage:
            return names
        else:
            return Common.removeModulesPackage(names)

    # 返回该包下所有模块，非递归查找
    @staticmethod
    def getModules(path, prefix, onerror=None):
        modules = []
        names = Common.getModulesName(path, prefix, onerror)
        for name in names:
            modules.append(Common.getModule(prefix + name))
        return modules

    # 重新加载模块
    @staticmethod
    def reloadModules(path, prefix, onerror=None):
        modules = Common.getModules(path, prefix, onerror)
        for module in modules:
            Common.reloadModule(module)

    # 根据模块名称，返回模块
    @staticmethod
    def getModule(moduleName):
        return importlib.import_module(moduleName)

    # 根据模块名称，重进加载模块
    # 传入module
    @staticmethod
    def reloadModule(module):
        importlib.reload(module)

    # 返回该包下所有模块的模块同名类，非递归查找
    @staticmethod
    def getClasses(path, prefix, onerror=None):
        classes = []
        names = Common.getModulesName(path, prefix, onerror)
        for name in names:
            classes.append(Common.getClass(prefix + name, name))
        return classes

    # 根据模块名称，返回指定的类
    @staticmethod
    def getClass(moduleName, name):
        module = Common.getModule(moduleName)
        return getattr(module, name)

    # 根据命令名称，返回模块名称
    @staticmethod
    def cmdToModuleName(cmd):
        list = cmd.split('-')
        name = ''
        for item in list:
            name += item.title()
        return name

    # 根据模块名称，返回命令名称
    @staticmethod
    def moduleNameToCmd(name):
        list = []
        # 解分每一个大写单词
        index = 0
        for i in range(0, len(name)):
            if name[i].isupper():
                if index != i:
                    list.append(name[index : i : 1].casefold())
                index = i
        # 加上最后一个单词
        list.append(name[index : len(name) + 1 : 1].casefold())
        return '-'.join(list)

    # 去除模块的路径，只保留名称
    @staticmethod
    def removeModulesPackage(moduleNames):
        names = []
        for moduleName in moduleNames:
            list = moduleName.split('.')
            index = len(list) - 1
            names.append(list[index])
        return names

    @staticmethod
    def inList(testList, list):
        for item in testList:
            if item not in list:
                return False
        return True

    @staticmethod
    def toBool(str):
        if not str or str == 'False' or str == 'false' or str == 'None' or str == 'null' or str == '0' or len(str) == 0:
            return False
        return True

    @staticmethod
    def toInt(str):
        if type(str) is int:
            return str
        try:
            num = int(str)
            return num
        except:
            return None

    # 查找需要被替换的模板
    # 返回字符串中要替换的变量名列表 如：['mytoken']
    @staticmethod
    def findReplaceVars(data):
        # 是否为字典
        if isinstance(data, dict):
            # 对象转为str
            data = json.dumps(data)
        # 定义正则匹配规则
        pattern = '\\${(.*?)}'
        return re.findall(pattern, data)

    # 参数模板替换 ${var}
    # 入参  oriData原始字符串,  replaceDict替换参考字典 如 {'mytoken': 'aaaaaa'}
    # 返回替换模板后的字符串
    @staticmethod
    def relaceTemplate(oristr, replaceDict):
        # 对象格式化为str
        if oristr is not str:
            oristr = json.dumps(oristr)
        templateOriData = Template(oristr)
        return json.loads(templateOriData.safe_substitute(**replaceDict))
